/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.ufba.lasid.v1.jitclouds.mda.dc;

import br.ufba.lasid.v1.jitclouds.mda.JitCloudsMDAFactory;
import br.ufba.lasid.v1.jitclouds.mda.MDA;
import br.ufba.lasid.v1.jitclouds.mda.api.JITDCFTControllerAPI;
import br.ufba.lasid.v1.jitclouds.mda.api.JiTFTManagerAPI;
import br.ufba.lasid.v1.jitclouds.mda.api.JiTMonitorAPI;
import br.ufba.lasid.v1.jitclouds.mda.datatypes.ICluster;
import br.ufba.lasid.v1.jitclouds.mda.datatypes.IDataCenter;
import static br.ufba.lasid.v1.jitclouds.mda.datatypes.enums.ComponentKind.*;
import static br.ufba.lasid.v1.jitclouds.mda.datatypes.enums.ContextKind.*;
import static br.ufba.lasid.v1.jitclouds.mda.datatypes.enums.MDAConstants.*;
import static br.ufba.lasid.v1.jitclouds.mda.datatypes.enums.ProcedureKind.*;
import br.ufba.lasid.v1.jitclouds.mda.datatypes.ft.IFailoverDeployer;
import br.ufba.lasid.v1.jitclouds.mda.datatypes.ft.IReplicableList;
import br.ufba.lasid.v1.jitclouds.mda.datatypes.report.Report;
import br.ufba.lasid.v1.jitclouds.mda.datatypes.virtualization.IHypervisor;
import br.ufba.lasid.v1.jitclouds.mda.datatypes.virtualization.INode;
import br.ufba.lasid.v1.jitclouds.mda.datatypes.virtualization.IVirtualMachine;
import br.ufba.lasid.v1.jitclouds.mda.datatypes.virtualization.IVirtualMachine.VMStatus;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author aliriosa
 */
public class JiTDCFTController implements JITDCFTControllerAPI{
    
    private IDataCenter DC;
    private JiTMonitorAPI monitor;
    private JiTFTManagerAPI manager;

    
    //private IFailoverDeployer deployer;
    
    @Override
    public void start() {
        try {
            /**
             * this method is going to be implemented when we integrate with MBF 
             * components.
             */            
            manager = MDA.createFTManager();
            monitor = MDA.createMonitor();
            
        } catch (Exception ex) {
            Logger.getLogger(JiTDCFTController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void stop() {
        /**
         * this method is going to be implemented when we integrate with MBF 
         * components.
         */        
    }

    @Override
    public Report installFailover(IReplicableList replicas) throws Exception{

        //Report r = new Report();
        
        Report r =
           JitCloudsMDAFactory.newReport(
                DCContext, 
                ControllerComponent, 
                VMFailoverDeploymentProcedure
           );
        
//        r.set(MDA.Context, Contexts.DCFailoverDeployment);
        
        try{
            
            /**
             * //we must verify if there is a failover already installed.
             * IReplicable primary = replicas.getPrimary();
             * 
             * if(hasInstalledFailover(primary)){
             *      r.set("status", "error");
             *      r.set("errorMessage", "failover already installed");
             *      return;
             * }
             * /
            
            
            /**
             * We use the MDA Facade to instante a default failover deployer 
             * which is made considering the base configuration of the MDA --
             * see MDA.base.properties file.
             */                        
            IFailoverDeployer deployer = MDA.createVMFailover();
            
             
            /**
             * The failover deployer must perform an atomic install -- it requires
             * to implement rollback procedures in order to recover state from 
             * unfinished deployments.
             */            
            deployer.install(replicas);
            
            r.set(Status.name(), "successful");
            
        }catch(Exception e){
            r.set(Status.name(), "error");
            r.set(ErrorMessage.name(), e.getMessage());
        }
        
        return r;
    }

    public IDataCenter getDC() {
        return DC;
    }

    public void setDC(IDataCenter DC) {
        this.DC = DC;
    }
        
    @Override
    public void checkStatus() {
        
      /**
       * For each cluster in DC
       */
      for(ICluster cluster : DC){
          
          /**
           * For each node in cluster
           */
          for(INode node : cluster){
              
              /**
               * For each hypervisor in node
               */
              for(IHypervisor h : node.getHypervisors()){
                  
                  /**
                   * For each machine in the hypervisor
                   */
                  for(IVirtualMachine m : h.getMachines()){
                      /**
                       * Get Machine ID
                       */
                      String resourceID = m.getID();
                      
                      /**
                       * Check Machine Status
                       */
                      VMStatus status = monitor.heartbeat(resourceID);
                      
                      /**
                       * If VM is faulty, then it'll notity the VM failure.
                       */
                      if(VMStatus.Faulty.equals(status)){
                          try {
                              manager.notifyFaulty(resourceID);
                          } catch (Exception ex) {
                              Logger.getLogger(JiTDCFTController.class.getName()).log(Level.SEVERE, null, ex);
                          }
                      }
                  }
              }
          }
      }
    }
    
}
